/* 
 * Enterprise Library Extensions - DI + ORM.
 * Copyright (C) 2006
 *
 * GNU General Public License
 *
 * This program is free software; you can redistribute 
 * it and/or modify it under the terms of the GNU General Public License 
 * as published by the Free Software Foundation; either version 2 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but 
 * WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 * See the GNU General Public License for more details.
 */
using System;
using System.Collections.Generic;
using ELE.EnterpriseLibrary.Naming;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

namespace ELE.EnterpriseLibrary.Common.Logging
{
	/// <summary>
	/// An abstract base class for objects that use logging to extend from
	/// </summary>
	public abstract class LoggingObjectBase
	{
    private bool mDebugOn = true;
    /// <summary>
    /// Hold the instance of the log writer
    /// </summary>
    protected LogWriter mLogger = null;
    private string mLoggerConfigFilePath;
    /// <summary>
    /// Path to the config file for the log writer
    /// </summary>
    public string LoggerConfigurationFilePath
    {
      set { mLoggerConfigFilePath = value; }
      get { return mLoggerConfigFilePath; }
    }
    /// <summary>
    /// The log writer
    /// </summary>
    public virtual LogWriter Logger
    {
      get 
      {
        if (mLogger == null && mLoggerConfigFilePath != null)
        {
          FileConfigurationSource fcs = new FileConfigurationSource(mLoggerConfigFilePath);
          LogWriterFactory lwr = new LogWriterFactory(fcs);
          mLogger = lwr.Create();
        }
        return mLogger; 
      }
      set
      {
        mLogger = value;
      }
    }
    /// <summary>
    /// Set debug flag on or of for this object 
    /// overriding the setting in the logger
    /// </summary>
    public bool DebugOn
    {
      get { return mDebugOn; }
      set { mDebugOn = value; }
    }
    /// <summary>
    /// Logs a debug message
    /// </summary>
    /// <param name="message"></param>
    public void LogDebug(string message)
    {
      LogDebug(message, null);
    }
    /// <summary>
    /// Logs a debug message
    /// </summary>
    /// <param name="message"></param>
    /// <param name="exception"></param>
    public void LogDebug(string message, Exception exception)
    {
      Log(message, exception, LogLevel.Debug);
    }
    /// <summary>
    /// Logs an info message
    /// </summary>
    /// <param name="message"></param>
    public void LogInfo(string message)
    {
      LogInfo(message, null);
    }
    /// <summary>
    /// Logs an info message
    /// </summary>
    /// <param name="message"></param>
    /// <param name="exception"></param>
    public void LogInfo(string message, Exception exception)
    {
      Log(message, exception, LogLevel.Information);
    }
    /// <summary>
    /// Logs an warning message
    /// </summary>
    /// <param name="message"></param>
    public void LogWarning(string message)
    {
      LogWarning(message, null);
    }
    /// <summary>
    /// Logs an warning message
    /// </summary>
    /// <param name="message"></param>
    /// <param name="exception"></param>
    public void LogWarning(string message, Exception exception)
    {
      Log(message, exception, LogLevel.Warning);
    }
    /// <summary>
    /// Logs an error message
    /// </summary>
    /// <param name="message"></param>
    public void LogError(string message)
    {
      LogError(message, null);
    }
    /// <summary>
    /// Logs an error message
    /// </summary>
    /// <param name="message"></param>
    /// <param name="exception"></param>
    public void LogError(string message, Exception exception)
    {
      Log(message, exception, LogLevel.Error);
    }
    /// <summary>
    /// Logs a message
    /// </summary>
    /// <param name="message"></param>
    /// <param name="exception"></param>
    /// <param name="level"></param>
    public void Log(string message, Exception exception, LogLevel level)
    {
      if(level == LogLevel.Debug)
      {
        if(!this.DebugOn)
        {
          //DebugOn flag overrides debug flag on the loggers
          return;
        }
      }
      if (this.Logger != null)
      {
        LogEntry entry = new LogEntry();
        entry.Message = message;
        entry.Categories = new List<string>();
        entry.Categories.Add(LoggingObjectBase.GetLevelCategoryName(level));
        entry.Win32ThreadId = System.Threading.Thread.CurrentThread.Name;
        entry.TimeStamp = System.DateTime.Now;
        if (exception != null)
        {
          entry.Message += "; " + System.Environment.NewLine + "\tException: " + exception.Message +
                        System.Environment.NewLine + "\tStacktrace: " + exception.StackTrace;
        }
        this.Logger.Write(entry);
      }
    }
    /// <summary>
    /// Copies the settings for <see cref="LoggerConfigurationFilePath"/>, and <see cref="DebugOn"/>
    /// to the target logging base object
    /// </summary>
    /// <param name="targetObj">Object to which we want to copy settings of this object</param>
    public void CopyLoggingSettings(LoggingObjectBase targetObj)
    {
      targetObj.LoggerConfigurationFilePath = this.LoggerConfigurationFilePath;
      targetObj.DebugOn = this.DebugOn;
    }
    /// <summary>
    /// Translates a loglevel into a recognizable identifier of a Category.
    /// </summary>
    /// <param name="level"></param>
    /// <returns></returns>
    public static string GetLevelCategoryName(LogLevel level)
    {
      switch (level)
      {
        case LogLevel.Information:
          return "Info";
        case LogLevel.Debug:
          return "Debug";
        case LogLevel.Warning:
          return "Warning";
        case LogLevel.Error:
          return "Error";
      }
      return "Unknown";
    }
	}
  /// <summary>
  /// Defines 4 basic logging levels 
  /// </summary>
  public enum LogLevel
  {
    /// <summary>
    /// Information category
    /// </summary>
    Information = 8,
    /// <summary>
    /// Debug category
    /// </summary>
    Debug = 4,
    /// <summary>
    /// Warning category
    /// </summary>
    Warning = 2,
    /// <summary>
    /// Error category
    /// </summary>
    Error = 1
  }
}
